<!doctype html>
<html lang="en-US">
  <head>
    <title>Collapsible activity</title>
    <link href="/assets/index.css" rel="stylesheet" type="text/css" />
    <script type="importmap">
      {
        "imports": {
          "react": "https://esm.sh/react@18.3.1",
          "react-dom": "https://esm.sh/react-dom@18.3.1",
          "react-dom/": "https://esm.sh/react-dom@18.3.1/",
          "@testduet/wait-for": "https://unpkg.com/@testduet/wait-for@main/dist/wait-for.mjs",
          "@fluentui/react-components": "https://esm.sh/@fluentui/react-components?deps=react@18.3.1&exports=FluentProvider,createDarkTheme,webLightTheme"
        }
      }
    </script>
    <script crossorigin="anonymous" src="/test-harness.js"></script>
    <script crossorigin="anonymous" src="/test-page-object.js"></script>
    <script type="module">
      import React from 'react';
      window.React = React;
    </script>
    <script defer crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
    <script defer crossorigin="anonymous" src="/__dist__/botframework-webchat-fluent-theme.development.js"></script>
    <style type="text/css">
      #webchat {
        width: 640px;
      }
      .fui-FluentProvider {
        height: 100%;
      }
    </style>
  </head>
  <body>
    <main id="webchat"></main>
    <script type="module">
      import React from 'react';
      import { createRoot } from 'react-dom/client';
      import { FluentProvider, createDarkTheme, webLightTheme } from '@fluentui/react-components';
      import { waitFor } from '@testduet/wait-for';

      async function openLastActivity() {
        let summaries;
        await waitFor(() => {
          summaries = Array.from(document.querySelectorAll('summary.collapsible-content__summary'));
          return summaries.length > 0;
        }, 500);

        summaries.at(-1).focus();
        await host.sendKeys('ENTER');

        await waitFor(() => {
          return summaries.at(-1).getAttribute('aria-expanded') === 'true';
        }, 500);

        await pageConditions.scrollStabilized();
      }

      run(async function () {
        const {
          WebChat: { FluentThemeProvider, ReactWebChat }
        } = window;

        const { directLine, store } = testHelpers.createDirectLineEmulator();

        const searchParams = new URLSearchParams(location.search);
        const variant = searchParams.get('variant');
        const theme = searchParams.get('fluent-theme');

        await host.windowSize(640, 1024, document.getElementById('webchat'));
        await host.sendDevToolsCommand('Emulation.setEmulatedMedia', {
          features: [
            { name: 'prefers-reduced-motion', value: 'reduce' },
            ...(theme === 'dark' || theme === 'light' ? [{ name: 'prefers-color-scheme', value: theme }] : [])
          ]
        });

        const root = createRoot(document.getElementById('webchat'));

        let fluentTheme;
        let codeBlockTheme;

        if (theme === 'dark' || (window.matchMedia('(prefers-color-scheme: dark)').matches && theme !== 'light')) {
          fluentTheme = {
            ...createDarkTheme({
              10: '#12174c',
              20: '#1a1f5b',
              30: '#21276a',
              40: '#293079',
              50: '#303788',
              60: '#384097',
              70: '#4049a7',
              80: '#151e80',
              90: '#4f59c5',
              100: '#5661d4',
              110: '#5e69e3',
              120: '#7982e8',
              130: '#949bec',
              140: '#afb5f1',
              150: '#c9cdf6',
              160: '#e4e6fa'
            }),
            colorNeutralBackground1Disabled: '#101010',
            colorNeutralBackground1Hover: '#101010',
            colorNeutralForeground5: '#424242'
          };
          codeBlockTheme = 'github-dark-default';
        } else {
          fluentTheme = {
            ...webLightTheme,
            // Original is #242424 which is too light for fui-FluentProvider to pass our a11y
            colorNeutralForeground1: '#1b1b1b'
          };
          codeBlockTheme = 'github-light-default';
        }

        // TODO: code block github theme triggers accessibility violation
        if (variant) {
          window.checkAccessibility = async () => {};
        }

        const webChatProps = { directLine, store, styleOptions: { codeBlockTheme } };

        root.render(
          variant
            ? React.createElement(
                FluentProvider,
                { className: 'fui-FluentProvider', theme: fluentTheme },
                React.createElement(
                  FluentThemeProvider,
                  { variant: variant },
                  React.createElement(ReactWebChat, webChatProps)
                )
              )
            : React.createElement(ReactWebChat, webChatProps)
        );

        await pageConditions.uiConnected();

        const CODE = `import numpy as np
import matplotlib.pyplot as plt

def plot_sine_waves():
    """Create a beautiful visualization of sine waves with different frequencies."""
    # Generate time points
    t = np.linspace(0, 10, 1000)

    # Create waves with different frequencies and phases
    wave1 = np.sin(t)
    wave2 = 0.5 * np.sin(2 * t + np.pi/4)
    wave3 = 0.3 * np.sin(3 * t + np.pi/3)

    # Combine waves
    combined = wave1 + wave2 + wave3

    # Create a stylish plot
    plt.style.use('seaborn-darkgrid')
    plt.figure(figsize=(12, 8))

    # Plot individual waves
    plt.plot(t, wave1, label='Primary Wave', alpha=0.5)
    plt.plot(t, wave2, label='Second Harmonic', alpha=0.5)
    plt.plot(t, wave3, label='Third Harmonic', alpha=0.5)

    # Plot combined wave with a thicker line
    plt.plot(t, combined, 'r-',
            label='Combined Wave',
            linewidth=2)

    plt.title('Harmonic Wave Composition', fontsize=14)
    plt.xlabel('Time', fontsize=12)
    plt.ylabel('Amplitude', fontsize=12)
    plt.legend()
    plt.grid(True, alpha=0.3)

    # Show the plot
    plt.tight_layout()
    plt.show()

# Generate the visualization
plot_sine_waves()`;

        const botIcon =
          '';

        const aiMessageEntity = {
          '@context': 'https://schema.org',
          '@id': '',
          '@type': 'Message',
          keywords: ['AIGeneratedContent', 'AnalysisMessage'],
          type: 'https://schema.org/Message',
          author: {
            '@context': 'https://schema.org',
            '@type': 'Person',
            image: botIcon,
            name: 'Agent'
          }
        };

        const waveSvg = `data:image/svg+xml;utf8,${encodeURIComponent(`
<svg width="400" height="200" viewBox="0 0 400 200" xmlns="http://www.w3.org/2000/svg">
  <!-- Primary Wave -->
  <path d="M0,100 C50,50 100,150 150,100 C200,50 250,150 300,100 C350,50 400,150 400,100"
        stroke="#3B82F6" fill="none" stroke-width="2" opacity="0.5"/>

  <!-- Second Harmonic -->
  <path d="M0,100 C25,75 50,125 75,100 C100,75 125,125 150,100 C175,75 200,125 225,100 C250,75 275,125 300,100 C325,75 350,125 375,100 C400,75 400,125 400,100"
        stroke="#10B981" fill="none" stroke-width="2" opacity="0.5"/>

  <!-- Combined Wave -->
  <path d="M0,100 C40,30 80,170 120,100 C160,30 200,170 240,100 C280,30 320,170 360,100 C380,65 400,135 400,100"
        stroke="#EF4444" fill="none" stroke-width="3"/>

  <!-- Grid Lines -->
  <line x1="0" y1="100" x2="400" y2="100" stroke="#CBD5E1" stroke-width="0.5" stroke-dasharray="4"/>
  <line x1="100" y1="0" x2="100" y2="200" stroke="#CBD5E1" stroke-width="0.5" stroke-dasharray="4"/>
  <line x1="200" y1="0" x2="200" y2="200" stroke="#CBD5E1" stroke-width="0.5" stroke-dasharray="4"/>
  <line x1="300" y1="0" x2="300" y2="200" stroke="#CBD5E1" stroke-width="0.5" stroke-dasharray="4"/>
</svg>`)}`;

        directLine.emulateIncomingActivity({
          from: { role: 'user' },
          type: 'message',
          text: `Message from user.`
        });

        directLine.emulateIncomingActivity({
          from: { role: 'bot' },
          entities: [
            {
              ...aiMessageEntity,
              keywords: []
            }
          ],
          id: 'a4c0c01d-c06e-4dde-9278-265c607b545b',
          type: 'typing',
          text: 'Informative…',
          channelData: {
            streamType: 'informative',
            streamSequence: 1
          }
        });

        await host.snapshot('local');

        directLine.emulateIncomingActivity({
          from: { role: 'bot' },
          entities: [
            {
              ...aiMessageEntity,
              keywords: [],
              abstract: 'Only abstract…'
            }
          ],
          channelData: {
            streamId: 'a4c0c01d-c06e-4dde-9278-265c607b545b',
            streamType: 'informative',
            streamSequence: 2
          },
          type: 'typing',
          id: 'a4c0c01d-c06e-4dde-9278-265c607b545b:1'
        });

        await host.snapshot('local');

        directLine.emulateIncomingActivity({
          from: { role: 'bot' },
          entities: [
            {
              ...aiMessageEntity,
              keywords: ['Collapsible'],
              abstract: 'Informative…',
              isBasedOn: {
                '@type': 'SoftwareSourceCode',
                programmingLanguage: 'python',
                text: CODE
              }
            }
          ],
          channelData: {
            streamId: 'a4c0c01d-c06e-4dde-9278-265c607b545b',
            streamType: 'informative',
            streamSequence: 3
          },
          type: 'typing',
          id: 'a4c0c01d-c06e-4dde-9278-265c607b545b:3',
          text: ''
        });

        await pageConditions.numActivitiesShown(2);

        await host.snapshot('local');

        await openLastActivity();

        await host.snapshot('local');

        directLine.emulateIncomingActivity({
          from: { role: 'bot' },
          entities: [
            {
              ...aiMessageEntity,
              keywords: ['Collapsible'],
              abstract: 'This is multiple lines text in abstract which is used to describe the content of the message.',
              isBasedOn: {
                '@type': 'SoftwareSourceCode',
                programmingLanguage: 'python',
                text: CODE
              }
            }
          ],
          channelData: {
            streamId: 'a4c0c01d-c06e-4dde-9278-265c607b545b',
            streamType: 'final',
            streamSequence: 4
          },
          id: 'a4c0c01d-c06e-4dde-9278-265c607b545b:4',
          type: 'message',
          text: `The final message has no View Code button as it is collapsible`
        });

        await host.snapshot('local');

        await host.sendKeys('ESCAPE');

        directLine.emulateIncomingActivity({
          from: { role: 'bot' },
          entities: [
            {
              ...aiMessageEntity,
              abstract: 'This is multiple lines text in abstract which is used to describe the content of the message.',
              isBasedOn: {
                '@type': 'SoftwareSourceCode',
                programmingLanguage: 'python',
                text: CODE
              }
            }
          ],
          type: 'message',
          text: `The non-collapsible message should have Show Code button`
        });

        await host.snapshot('local');

        // Generated from https://placeholder.pics/svg/320x180.
        const LANDSCAPE_SVG = `data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="320" height="180"><rect x="2" y="2" width="316" height="176" style="fill:%23DEDEDE;stroke:%23555555;stroke-width:2"/><text x="50%" y="50%" font-size="18" text-anchor="middle" alignment-baseline="middle" font-family="monospace, sans-serif" fill="%23555555">320×180 (16:9)</text></svg>`;

        // Generated from https://placeholder.pics/svg/180x320.
        const PORTRAIT_SVG = `data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="180" height="320"><rect x="2" y="2" width="176" height="316" style="fill:%23DEDEDE;stroke:%23555555;stroke-width:2"/><text x="50%" y="50%" font-size="18" text-anchor="middle" alignment-baseline="middle" font-family="monospace, sans-serif" fill="%23555555">180×320 (9:16)</text></svg>`;

        // Generated from https://placeholder.pics/svg/640x180.
        const WIDE_SVG = `data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="640" height="180"><rect x="2" y="2" width="636" height="176" style="fill:%23DEDEDE;stroke:%23555555;stroke-width:2"/><text x="50%" y="50%" font-size="18" text-anchor="middle" alignment-baseline="middle" font-family="monospace, sans-serif" fill="%23555555">640×180 (32:9)</text></svg>`;

        directLine.emulateIncomingActivity({
          from: { role: 'bot' },
          id: '41.0',
          text: '',
          entities: [
            {
              ...aiMessageEntity,
              keywords: ['Collapsible'],
              abstract: 'Collapsible activity with multiple attachments and code, but no body',
              isBasedOn: {
                '@type': 'SoftwareSourceCode',
                programmingLanguage: 'python',
                text: "print('Hello World!')"
              }
            }
          ],
          attachments: [
            {
              contentType: 'image/jpeg',
              contentUrl:
                'https://raw.githubusercontent.com/compulim/BotFramework-MockBot/master/public/assets/surface1.jpg',
              name: 'front of Surface Pro'
            },
            {
              contentType: 'image/jpeg',
              contentUrl:
                'https://raw.githubusercontent.com/compulim/BotFramework-MockBot/master/public/assets/surface2.jpg',
              name: 'back of Surface Pro'
            }
          ],
          type: 'message'
        });

        await host.snapshot('local');

        await openLastActivity();

        await host.snapshot('local');
      });
    </script>
  </body>
</html>
